# -*- coding: utf-8 -*-
import pandas as pd

from core.dataClasses import StockTradeDataColumnName, TacticResultData
from core.enums import Period, EventType
from core.tactic import Tactic
from functions import *
from core import logger


class TradeBuyPointTactic(Tactic):
    classInfo = "交易点位策略"

    def __init__(self, classify: str, sourceClassify: str, unnoticeClassify: str, volIncreaseRatio: float = 1.4):
        super(TradeBuyPointTactic, self).__init__()
        self.classify: str = classify
        self.sourceClassify: str = sourceClassify
        self.unnoticeClassify: str = unnoticeClassify
        self.volIncreaseRatio: float = volIncreaseRatio

    def compute(self) -> bool:
        self.setPeriod(self.period)
        clo = close()
        rtq: pd.DataFrame = realtimeQuote()
        if rtq is None or rtq.empty:
            return False

        if clo.count() < 15:
            logger.info("数据量小于最低计算数")
            return False
        volume = vol()
        op = open()
        cloExtra = clo
        cloExtra[rtq.index[0]] = rtq[StockTradeDataColumnName.CLOSE.value].values[0]
        ma10 = sma(cloExtra[-15:], 10)
        ma5 = sma(cloExtra[-15:], 5)

        judgment = cloExtra[-2] < ma10[-2] or op[-1] < ma10[-1]  # 倒数第二次收盘价小于10日均价 或 最新开盘价小于10日均价
        if judgment:
            judgment = judgment and cloExtra[-1] > ma10[-1]  # 最后收盘价高于10日均价线
        # if judgment:
        #     judgment = judgment and ma5[-2] < ma10[-2] and ma5[-1] >= ma10[-1] # 金叉
        if judgment:
            judgment = judgment and op[-1] < cloExtra[-1]  # 阳线
        # if judgment:
        #     judgment = judgment and rtq[StockTradeDataColumnName.VOL.value].values[0] > volume[
        #         -2] * self.volIncreaseRatio  # 成交量放量指定倍数
        if judgment:
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(
                EventType.TRADE_BUY).setSecurity(self.context.security).setDt(
                self.clock.getDateTime()).setIsInRealtime(self.clock.isInRealTradeTime()).setPrice(
                cloExtra[-1]).setClassify(self.classify).setSourceClassify(self.sourceClassify)
            self.emit(tacticResultData)
            return True
        # 收盘价在10均价下方
        # if cloExtra[-1] > ma10[-1]:
        #     self.emit(TacticResultData(period=self.period, eventType=EventType.TACTIC_UNMONITOR,
        #                                security=self.context.security, dt=self.clock.getDateTime(),
        #                                isInRealtime=self.clock.isInRealTradeTime(), classify=self.unnoticeClassify,
        #                                sourceClassify=self.sourceClassify))
        #     return True
        return False


class TradeSellPointTactic(Tactic):
    classInfo = "交易点位策略"

    def __init__(self, classify: str, sourceClassify: str, volIncreaseRatio: float = 1.2):
        super(TradeSellPointTactic, self).__init__()
        self.classify: str = classify
        self.sourceClassify: str = sourceClassify
        self.volIncreaseRatio: float = volIncreaseRatio

    def compute(self) -> bool:
        self.setPeriod(self.period)
        clo = close()
        rtq: pd.DataFrame = realtimeQuote()
        if rtq is None or rtq.empty:
            return False

        if clo.count() < 10:
            logger.info("数据量小于最低计算数")
            return False
        clo[rtq.index[0]] = rtq[StockTradeDataColumnName.CLOSE.value].values[0]
        hi = high()
        hi[rtq.index[0]] = rtq[StockTradeDataColumnName.HIGH.value].values[0]
        op = open()
        # 如果出现长的上影线，则卖出
        if (clo[-1] > op[-1] and hi[-1] - clo[-1] > clo[-1] - op[-1]) or (clo[-1] <= op[-1] and hi[-1] - op[-1] > op[-1] - clo[-1]):
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(EventType.TRADE_SELL).setSecurity(
                self.context.security).setDt(self.clock.getDateTime()).setIsInRealtime(
                self.clock.isInRealTradeTime()).setPrice(clo[-1]).setClassify(self.classify).setSourceClassify(
                self.sourceClassify)
            self.emit(tacticResultData)
            return True
        ma10 = sma(clo, 10)
        judgment = clo[-1] < ma10[-1]  # 收盘价跌破10日均价
        if judgment:
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(EventType.TRADE_SELL).setSecurity(self.context.security).setDt(self.clock.getDateTime()).setIsInRealtime(self.clock.isInRealTradeTime()).setPrice(ma10[-1]).setClassify(self.classify).setSourceClassify(self.sourceClassify)
            self.emit(tacticResultData)
            return True
        ma5 = sma(clo, 5)
        judgment = clo[-2] - clo[-1] > 0 # 收盘价下跌
        judgment = judgment and (clo[-2] - clo[-1]/clo[-2]) * 100 > 4 # 收盘价下跌幅度大于4%
        judgment = judgment and clo[-1] < ma5[-1] # 最后收盘价小于5日均价
        judgment = judgment and clo[-2] > ma5[-2] # 倒数第二次收盘价 大于5日均价
        if judgment:
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(EventType.TRADE_SELL).setSecurity(
                self.context.security).setDt(self.clock.getDateTime()).setIsInRealtime(
                self.clock.isInRealTradeTime()).setPrice(ma10[-1]).setClassify(self.classify).setSourceClassify(
                self.sourceClassify)
            self.emit(tacticResultData)
            return True

        return False


class MaNoticeTactic(Tactic):
    classInfo = "需要监测的股票"

    def __init__(self, classify: str, sourceClassify: str):
        super(MaNoticeTactic, self).__init__()
        self.classify: str = classify
        self.sourceClassify: str = sourceClassify

    def compute(self):
        self.setPeriod(self.period)
        clo = close()
        cloLast10 = clo[-12:]
        cloLast10Ma10 = sma(cloLast10, 10)
        # 收盘价在10均价下方
        if cloLast10[-1] < cloLast10Ma10[-1]:
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(
                EventType.TACTIC_MONITOR).setSecurity(self.context.security).setDt(
                self.clock.getDateTime()).setIsInRealtime(self.clock.isInRealTradeTime()).setClassify(self.classify).setSourceClassify(self.sourceClassify)
            self.emit(tacticResultData)
            return True
        return False


class MaUnnoticeTactic(Tactic):
    classInfo = "需要监测的股票"

    def __init__(self, classify: str, sourceClassify: str):
        super(MaUnnoticeTactic, self).__init__()
        self.classify: str = classify
        self.sourceClassify: str = sourceClassify

    def compute(self):
        self.setPeriod(self.period)
        clo = close()
        cloLast10 = clo[-12:]
        cloLast10Ma10 = sma(cloLast10, 10)
        # 收盘价在10均价下方
        if cloLast10[-1] > cloLast10Ma10[-1]:
            tacticResultData = TacticResultData().setPeriod(self.period).setEventType(
                EventType.TACTIC_UNMONITOR).setSecurity(self.context.security).setDt(
                self.clock.getDateTime()).setIsInRealtime(self.clock.isInRealTradeTime()).setClassify(
                self.classify).setSourceClassify(self.sourceClassify)
            self.emit(tacticResultData)
            return True
        return False

